package kevin.hbase.service;

import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import kevin.hbase.bean.HbaseGps;
import kevin.hbase.bean.StopInfo;
import kevin.hbase.mapper.StopMapper;
import kevin.hbase.util.DateTimeUtil;
import kevin.hbase.util.GpsUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
public class StopService {
    @Autowired
    private HbaseService hbaseService;
    @Autowired
    private StopMapper stopMapper;

    @Value("${stop.file}")
    private String stopFile;

    public void stop() {
        String inExcelFile = "/opt/stop-ly.xlsx";
        String outExcelFile = "/opt/stop-ly-result.xlsx";
        List<StopInfo> stopInfos = new ArrayList<>();
        ExcelReader reader = ExcelUtil.getReader(inExcelFile);
        List<List<Object>> lists = reader.read();
        List<List<Object>> dataList = lists.subList(1, lists.size());
        String endTime = DateTimeUtil.getDateTimeAsString(LocalDateTime.now(), DateTimeUtil.DATETIME_FORMAT);
        for (List<Object> objects : dataList) {
            try {
                String vin = objects.get(0).toString();
                String deviceId = objects.get(1).toString();
                String startTime = objects.get(2).toString();
                List<StopInfo> list = stopTimeAnalyse(vin, deviceId, startTime, endTime);
                stopInfos.addAll(list);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }

        List<Map<String, Object>> rows = new ArrayList<>();
        try {
            for (StopInfo stopInfo : stopInfos) {
                Map<String, Object> row = new LinkedHashMap();
                row.put("车架号", stopInfo.getVin());
                row.put("设备号", stopInfo.getCallLetter());
                row.put("停车开始时间", stopInfo.getStopStartTimeStr());
                row.put("停车结束时间", stopInfo.getStopEndTimeStr());
                row.put("停车时长（分钟）", stopInfo.getStopTime() / 60);
                row.put("经纬度", stopInfo.getLongitude() + "," + stopInfo.getLatitude());
                row.put("参考位置", stopInfo.getRefer());
                rows.add(row);
            }
            ExcelWriter writer = ExcelUtil.getWriter(outExcelFile);
            writer.write(rows, true);
            writer.close();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    private List<StopInfo> stopTimeAnalyse(String vin, String callLetter, String startTime, String endTime) throws Exception {
        LocalDateTime start = DateTimeUtil.parseStringToDateTime(startTime, DateTimeUtil.DATETIME_FORMAT);
        LocalDateTime end = DateTimeUtil.parseStringToDateTime(endTime, DateTimeUtil.DATETIME_FORMAT);
        LocalDateTime startDateTime = start;
        LocalDateTime endDateTime;
        List<StopInfo> stopInfos = new ArrayList<>();
        StopInfo stopInfo = null;
        for (; ; ) {
            endDateTime = startDateTime.plusDays(1);
            String startDateTimeStr = DateTimeUtil.getDateTimeAsString(startDateTime, DateTimeUtil.DATETIME_FORMAT);
            String endDateTimeStr = DateTimeUtil.getDateTimeAsString(endDateTime, DateTimeUtil.DATETIME_FORMAT);
            List<HbaseGps> hbaseGpsList = hbaseService.getHistoryGps(callLetter, startDateTimeStr, endDateTimeStr);
            for (HbaseGps hbaseGps : hbaseGpsList) {
                int speed = hbaseGps.getSpeed();
                if (speed == 0) {
                    if (stopInfo == null) {
                        stopInfo = new StopInfo();
                        stopInfo.setStopStartTime(hbaseGps.getGpsTime());
                        stopInfo.setLatitude(hbaseGps.getLatitude());
                        stopInfo.setLongitude(hbaseGps.getLongitude());
                    }
                    stopInfo.setStopEndTime(hbaseGps.getGpsTime());
                    long stopTime = stopInfo.getStopEndTime() - stopInfo.getStopStartTime();
                    stopTime = stopTime / 1000;
                    stopInfo.setStopTime(stopTime);
                } else {
                    if (stopInfo != null) {
                        if (stopInfo.getStopTime() >= 3 * 60 * 60) {
                            stopInfo.setRefer(GpsUtils.regeoByBaidu(stopInfo.getLongitude(), stopInfo.getLatitude()));
                            stopInfo.setStopStartTimeStr(DateTimeUtil.getDateTimeGMT8AsString(stopInfo.getStopStartTime(), DateTimeUtil.DATETIME_FORMAT));
                            stopInfo.setStopEndTimeStr(DateTimeUtil.getDateTimeGMT8AsString(stopInfo.getStopEndTime(), DateTimeUtil.DATETIME_FORMAT));
                            stopInfo.setCallLetter(callLetter);
                            stopInfo.setVin(vin);
                            log.info("{} stop time exceed 3 hours,stopInfo:{}", callLetter, stopInfo);
                            stopInfos.add(stopInfo);
                        }
                    }
                    stopInfo = null;
                }
            }
            startDateTime = endDateTime;
            if (endDateTime.isAfter(end)) {
                break;
            }
        }
        return stopInfos;
    }

    public List<Map<String, Object>> getStopDeviceList() {
        List<Map<String, Object>> list = new ArrayList<>();
        ExcelReader reader = ExcelUtil.getReader(stopFile);
        List<List<Object>> lists = reader.read();
        List<List<Object>> dataList = lists.subList(1, lists.size());
        for (List<Object> objects : dataList) {
            try {
                String vin = objects.get(0).toString();
                String deviceId = objects.get(1).toString();
                String startTime = objects.get(2).toString();
                Map<String, Object> map = new HashMap<>();
                map.put("deviceId", deviceId);
                map.put("vin", vin);
                map.put("startTime", startTime);
                list.add(map);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return list;
    }

    public void stopAnalyse(List<Map<String, Object>> list) {
        String endTime = DateTimeUtil.getDateTimeAsString(LocalDateTime.now(), DateTimeUtil.DATETIME_FORMAT);
        List<StopInfo> stopInfos = new ArrayList<>();
        for (Map<String, Object> map : list) {
            String deviceId = map.get("deviceId").toString();
            String vin = map.get("vin").toString();
            String startTime = map.get("startTime").toString();
            try {
                List<StopInfo> stopInfoList = stopTimeAnalyse(vin, deviceId, startTime, endTime);
                stopInfos.addAll(stopInfoList);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }

        int totalSize = stopInfos.size();
        if (totalSize <= 0) {
            return;
        }
        int batchSaveSize = 100;
        int batchNum = totalSize % batchSaveSize == 0 ? (totalSize / batchSaveSize) : (totalSize / batchSaveSize + 1);
        List<StopInfo> subList;
        for (int i = 0; i < batchNum; i++) {
            if (i == batchNum - 1) {
                subList = stopInfos.subList(i * batchSaveSize, totalSize);
            } else {
                subList = stopInfos.subList(i * batchSaveSize, (i + 1) * batchSaveSize);
            }
            if (!subList.isEmpty()) {
                stopMapper.saveStops(subList);
            }
        }
    }
}
